package com.tbit.uqbike.center.service.impl;

import com.tbit.uqbike.center.constant.SystemData;
import com.tbit.uqbike.center.dao.core.AccountConfigExtDao;
import com.tbit.uqbike.center.dao.ter.TerAttrExDao;
import com.tbit.uqbike.center.dao.ter.TerBatteryDao;
import com.tbit.uqbike.center.dao.ter.TerPositionDao;
import com.tbit.uqbike.center.pojo.*;
import com.tbit.uqbike.center.service.*;
import com.tbit.uqbike.center.util.LogUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service("quartzJobService")
@Slf4j
public class QuartzJobServiceImpl implements QuartzJobService {
    @Autowired
    private TerPositionDao terPositionDao;
    @Autowired
    private TerBatteryDao terBatteryDao;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private MachineBatteryModelService machineBatteryModelService;
    @Autowired
    private BatteryModelDetailService batteryModelDetailService;
    @Autowired
    private BatteryModelService batteryModelService;
    @Autowired
    private TerAttrExDao terAttrExDao;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Autowired
    private BatteryBmsService batteryBmsService;

    @Override
    @Scheduled(cron = "0 0/1 * * * ?")
    public void synNewMachineData() {
        try {
            if (SystemData.lastSynTime != null) {
                Boolean isLoad = false;

                /**判断时间是否超过60分钟，超过重新全量加载一次*/
                if ((System.currentTimeMillis() - SystemData.lastSynTime) > 3600000) {
                    isLoad = true;
                    LogUtil.info("60分钟超时触发设备同步");
                } else {
                    /**判断设备是否变化*/
                    Integer machineCount = machineService.getCount();
                    if (machineCount > 0 && SystemData.machineNOMachineIdMap.size() != machineCount) {
                        isLoad = true;
                        LogUtil.info("设备总数变化触发设备同步");
                    }
                    /**最大设备id*/
                    Integer maxMachineId = machineService.getMaxMachineId();
                    if (SystemData.maxMachineId != null && maxMachineId != null && !maxMachineId.equals(SystemData.maxMachineId)) {
                        isLoad = true;
                        LogUtil.info("设备id最大变化触发设备同步");
                    }
                    SystemData.maxMachineId = maxMachineId;
                }

                if (isLoad) {
                    /**加载所有设备信息*/
                    List<MachineBase> machineBases = machineService.getAllMachineBase();
                    Map<String, Integer> machineNOMachineIdMap = new ConcurrentHashMap<String, Integer>();
                    Map<Integer, Integer> machineIdAccountIdMap = new ConcurrentHashMap<Integer, Integer>();
                    for (MachineBase machineBase : machineBases) {
                        machineNOMachineIdMap.put(machineBase.getMachineNO(), machineBase.getMachineId());
                        machineIdAccountIdMap.put(machineBase.getMachineId(), machineBase.getAccountId());
                    }

                    /**替换内存数据*/
                    SystemData.machineNOMachineIdMap = machineNOMachineIdMap;
                    SystemData.machineIdAccountIdMap = machineIdAccountIdMap;

                    /**更新最后同步时间*/
                    SystemData.lastSynTime = System.currentTimeMillis();

                    LogUtil.info("同步设备数据[" + machineBases.size() + "]");
                }
            }
        }catch (Exception e){
            log.error("同步设备数据异常",e);
        }
    }

    @Override
    @Scheduled(cron = "0 0/1 * * * ?")
    public synchronized void synBatteryData() {
        try {
            long startTime = System.currentTimeMillis();

            /**所有电池方案*/
            Map<Integer, BatteryModel> batteryModelMap = new HashMap<Integer, BatteryModel>();
            List<BatteryModel> batteryModels = batteryModelService.getAll();
            for (BatteryModel bm : batteryModels) {
                batteryModelMap.put(bm.getBatteryModelId(), bm);
            }

            /** 加载所有设备电池方案对应信息 */
            List<MachineBatteryModel> machineBatteryModels = machineBatteryModelService.getAll();
            Map<Integer, Integer> machineIdBatteryModelIdMap = new HashMap<Integer, Integer>();
            Map<Integer, Integer> machineIdSecondaryBatteryModelIdMap = new HashMap<Integer, Integer>();
            for (MachineBatteryModel machineBatteryModel : machineBatteryModels) {
                machineIdBatteryModelIdMap.put(machineBatteryModel.getMachineId(), machineBatteryModel.getBatteryModelId());
                /**兼容氢电池辅助电池方案*/
                if (machineBatteryModel.getSecondaryBattertId() != null) {
                    machineIdSecondaryBatteryModelIdMap.put(machineBatteryModel.getMachineId(), machineBatteryModel.getSecondaryBattertId());
                }
            }

            /** 加载电池方案详情数据 */
            List<BatteryModelDetail> batteryModelDetails = batteryModelDetailService.getAll();
            Map<Integer, List<BatteryModelDetail>> batteryModelListMap = new HashMap<Integer, List<BatteryModelDetail>>();
            for (BatteryModelDetail batteryModelDetail : batteryModelDetails) {
                if (!batteryModelListMap.containsKey(batteryModelDetail.getBatteryModelId())) {
                    batteryModelListMap.put(batteryModelDetail.getBatteryModelId(), new ArrayList<BatteryModelDetail>());
                }

                /** 添加 */
                batteryModelListMap.get(batteryModelDetail.getBatteryModelId()).add(batteryModelDetail);
            }

            Map<Integer, AccountConfigExt> accountConfigExtMap = new HashMap<>();
            Map<String, Object> map = new HashMap<>();
            map.put("paramKey", "socPower");
            List<AccountConfigExt> accountConfigExtList = accountConfigExtDao.getByParamKey(map);
            for (AccountConfigExt item : accountConfigExtList) {
                accountConfigExtMap.put(item.getAccountId(), item);
            }

            /** 更换内存数据 */
            SystemData.batteryModelMap = batteryModelMap;
            SystemData.machineIdBatteryModelIdMap = machineIdBatteryModelIdMap;
            SystemData.machineIdSecondaryBatteryModelIdMap = machineIdSecondaryBatteryModelIdMap;
            SystemData.batteryModelListMap = batteryModelListMap;
            SystemData.AccountConfigExtMap = accountConfigExtMap;

            LogUtil.info("[" + batteryModelDetails.size() + "]同步电池方案数据耗时" + (System.currentTimeMillis() - startTime) + "ms");
        }catch (Exception e){
            log.error("同步电池方案数据异常",e);
        }
    }

    @Override
    @Scheduled(cron = "0/10 * * * * ?")
    public void updateBatteryInfo() {
        try {
            long startTime = System.currentTimeMillis();

            /** 复制数据 */
            Map<Integer, Integer> needUpdateBatteryMap = new HashMap<Integer, Integer>(SystemData.needUpdateBatteryMap);
            /** 清空数据 */
            SystemData.needUpdateBatteryMap.clear();

            List<MachineStatus> machineStatuses = new ArrayList<MachineStatus>();

            for (Integer machineId : needUpdateBatteryMap.keySet()) {
                MachineStatus machineStatus = batteryModelDetailService.updateMachineBattery(machineId);

                /** 筛选没有定位上的设备 */
                if (machineStatus != null && machineStatus.getPosDt() != null) {
                    machineStatuses.add(SystemData.machineStatusMap.get(machineId));
                }
            }
            /** 保存到数据库 */
            if (machineStatuses.size() > 0) {
                Integer batchNumber = 1000;

                /** 分批更新 */
                Integer number = machineStatuses.size() / batchNumber;
                if (machineStatuses.size() % batchNumber > 0) {
                    number++;
                }

                for (int i = 0; i < number; i++) {
                    int start = i * batchNumber;
                    int end = (i + 1) * batchNumber;
                    if (i == (number - 1)) {
                        end = machineStatuses.size();
                    }

                    machineStatusService.updateBatch(machineStatuses.subList(start, end));
                }
            }

            /** 复制数据 */
            Map<String, TerAttrEx> lithiumMap = new HashMap<String, TerAttrEx>(SystemData.lithiumMap);
            /** 清空数据 */
            SystemData.lithiumMap.clear();


            if (lithiumMap.size() > 0) {
                List<TerAttrEx> terAttrExes = new ArrayList<>();
                for (String machineNO : lithiumMap.keySet()) {
                    terAttrExes.add(lithiumMap.get(machineNO));
                }
                Integer batchNumber = 1000;

                /** 分批更新 */
                Integer number = terAttrExes.size() / batchNumber;
                if (terAttrExes.size() % batchNumber > 0) {
                    number++;
                }

                for (int i = 0; i < number; i++) {
                    int start = i * batchNumber;
                    int end = (i + 1) * batchNumber;
                    if (i == (number - 1)) {
                        end = terAttrExes.size();
                    }
                    terAttrExDao.updateBatch(terAttrExes.subList(start, end));
                    LogUtil.info("批量更新氢燃料锂电池数据[" + lithiumMap.size() + "个][" + (System.currentTimeMillis() - startTime) + "ms]");
                }
            }


            LogUtil.info("批量更新电量数据[" + needUpdateBatteryMap.size() + "个][" + (System.currentTimeMillis() - startTime) + "ms]");

        }catch (Exception e){
            log.error("批量更新电量数据异常",e);
        }
    }

    @Override
    @Scheduled(cron = "0 0/1 * * * ?")
    public void updateTerToLastStatus() {
        try {
            long startTime = System.currentTimeMillis();

            /** 加载所有设备信息 */
            List<MachineBase> machineBases = machineService.getAllMachineBase();
            for (MachineBase machineBase : machineBases) {
                SystemData.machineNOMachineIdMap.put(machineBase.getMachineNO(), machineBase.getMachineId());
                SystemData.machineIdAccountIdMap.put(machineBase.getMachineId(), machineBase.getAccountId());
                SystemData.machineIdMachineMap.put(machineBase.getMachineId(), machineBase);
            }

            /** 加载所有最后位置数据 */
            Map<String, TerPosition> terPositionMap = new HashMap<String, TerPosition>();
            List<TerPosition> terPositions = terPositionDao.getAll();
            for (TerPosition terPosition : terPositions) {
                terPositionMap.put(terPosition.getMachineNO(), terPosition);
            }

            /** 加载所有最后电量数据 */
            Map<String, TerBattery> terBatteryMap = new HashMap<String, TerBattery>();
            List<TerBattery> terBatterys = terBatteryDao.getAll();
            for (TerBattery terBattery : terBatterys) {
                terBatteryMap.put(terBattery.getMachineNO(), terBattery);
            }

            for (MachineBase machineBase : machineBases) {
                String machineNO = machineBase.getMachineNO();
                TerPosition terPosition = terPositionMap.get(machineNO);
                TerBattery terBattery = terBatteryMap.get(machineNO);

                /**不存在的更新*/
                MachineStatus machineStatus = SystemData.machineStatusMap.get(machineBase.getMachineId());
                if (machineStatus == null) {
                    machineStatus = new MachineStatus();

                    machineStatus.setMachineId(machineBase.getMachineId());
                    if (terPosition != null) {
                        machineStatus.setPosDt(terPosition.getDt());
                        machineStatus.setLon(terPosition.getLon());
                        machineStatus.setLat(terPosition.getLat());
                        machineStatus.setTerStatus(terPosition.getCarStatus());
                    }

                    if (terBattery != null) {
                        machineStatus.setBatDt(terBattery.getDt());
                        machineStatus.setSoc(terBattery.getSoc());
                        machineStatus.setBatteryEI(terBattery.getBatteryEI());
                        machineStatus.setBatteryEU(terBattery.getBatteryEU());
                        machineStatus.setBmsErr(0);
                    }

                    SystemData.machineStatusMap.put(machineStatus.getMachineId(), machineStatus);
                }

            }
            List<Battery> batteries = batteryBmsService.getByMachineId();
            if (!batteries.isEmpty()) {
                for (Battery b : batteries) {
                    if (b.getMachineId() == null) {
                        continue;
                    }
                    SystemData.machineIdBatteryMap.put(b.getMachineId(), b.getBatteryNO());
                }
            }

            List<MachineStatus> machineStatuses = new ArrayList<MachineStatus>();

            for (MachineBase machineBase : machineBases) {
                MachineStatus machineStatus = batteryModelDetailService.updateMachineBattery(machineBase.getMachineId());

                /** 筛选沒有电量时间、没有定位上的设备 */
                if (machineStatus != null && machineStatus.getPosDt() != null && machineStatus.getBatDt() != null) {
                    machineStatuses.add(SystemData.machineStatusMap.get(machineBase.getMachineId()));
                }
            }

            /** 保存到数据库 */
            if (machineStatuses.size() > 0) {
                Integer batchNumber = 1000;

                /** 分批更新 */
                Integer number = machineStatuses.size() / batchNumber;
                if (machineStatuses.size() % batchNumber > 0) {
                    number++;
                }

                for (int i = 0; i < number; i++) {
                    int start = i * batchNumber;
                    int end = (i + 1) * batchNumber;
                    if (i == (number - 1)) {
                        end = machineStatuses.size();
                    }

                    machineStatusService.updateBatch(machineStatuses.subList(start, end));
                }
            }

            LogUtil.info("全量更新电量位置信息[" + machineStatuses.size() + "个][" + (System.currentTimeMillis() - startTime) + "ms]");
        }catch (Exception e){
           log.error("全量更新电量位置信息异常",e);
        }

    }

}